import * as Cesium from "cesium";
// import { useCesiumStore } from "@/stores/useCesiumStore.js";
// import { toRaw } from "vue";

export const MeasureArea = (viewer) => {
  //   const viewer = toRaw(useCesiumStore().viewer); //获取viewer对象
  const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); //创建屏幕空间事件处理器
  viewer.scene.canvas.style.cursor = "crosshair";

  let p = []; //存储要计算面积的点
  let pCartographic = []; //存储计算距离与添加label的点
  let activeShapePoints = []; //存储当前正在绘制的多边形顶点坐标
  let activeShape = null; //当前正在绘制的多边形
  let floatingPoint = null; //作为第一个点，用于判断是否开始获取鼠标移动结束位置

  //定义变量，进行角度和弧度之间的转换；弧度=pi/180*度数,角度=弧度*180/pi
  const radiansPerDegree = Math.PI / 180.0; //角度转弧度
  const degreesPerRadian = 180.0 / Math.PI; //弧度转角度

  //计算两点朝向，从A点到B点相对于平面X轴的平面角度的函数getBearing
  //from:起点
  //to:终点
  const getBearing = (from, to) => {
    from = Cesium.Cartographic.fromCartesian(from); //将Cartesian3坐标转换为Cartographic坐标
    to = Cesium.Cartographic.fromCartesian(to);
    const lat1 = from.latitude * radiansPerDegree; //起点纬度弧度
    const lon1 = from.longitude * radiansPerDegree; //起点经度弧度
    const lat2 = to.latitude * radiansPerDegree; //终点纬度弧度
    const lon2 = to.longitude * radiansPerDegree; //终点经度弧度
    //返回从原点（0，0）到（x，y）点的线段与x轴正方向夹角的弧度值，转为角度
    let angle = -Math.atan2(
      Math.sin(lon1 - lon2) * Math.cos(lat2),
      Math.cos(lat1) * Math.sin(lat2) -
        Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
    );
    if (angle < 0) {
      angle += 2 * Math.PI;
    }
    return angle * degreesPerRadian; //返回角度值
  };

  //计算3个点直接连线的角度的函数getAngle
  /* p1,p2,p3:三点坐标 ,分别计算相邻两点的朝向，并根据两个线段朝向计算，得到3个点连城的夹角*/
  const getAngle = (p1, p2, p3) => {
    const bearing1 = getBearing(p2, p1); //相邻两点的朝向
    const bearing2 = getBearing(p2, p3);
    let angle = bearing2 - bearing1; //两个线段的夹角
    if (angle < 0) {
      angle += 360;
    }
    return angle;
  };

  //封装计算相邻两点距离函数getDistance,根据相邻两点之间经纬度、高度计算两点之间的空间距离
  const getDistance = (p1, p2) => {
    const geodesic = new Cesium.EllipsoidGeodesic(); //创建椭球体几何对象
    geodesic.setEndPoints(p1, p2); //设置起点和终点
    //获取起点和终点之间的表面距离
    let s = geodesic.surfaceDistance;
    //获取起点和终点之间的表面距离的平方
    s = Math.sqrt(Math.pow(s, 2) + Math.pow(p1.height - p2.height, 2));
    return s; //返回距离值
  };

  //计算多边形面积的函数getArea
  /* points:多边形顶点坐标数组 
    将多边形拆分成三角曲面，通过计算每3个点组成的线段的夹角及两条边的长度分别计算三角形的面积，然后将所有三角形面积相加*/
  const getArea = (points) => {
    let res = 0;
    for (let i = 0; i < points.length - 2; i++) {
      const j = (i + 1) % points.length; //相邻点的第二个点
      const k = (i + 2) % points.length; //相邻点的第三个点
      const totalAngle = getAngle(points[i], points[j], points[k]).toFixed(); //计算相邻两点的夹角
      const distance1 = getDistance(pCartographic[i], pCartographic[j]); //计算两点之间的距离
      const distance2 = getDistance(pCartographic[j], pCartographic[k]);
      // console.log(j,k,distance1,distance2,totalAngle);
      //计算三角形面积
      res +=
        distance1 *
        distance2 *
        Math.abs(
          Math.round(Math.sin(totalAngle * radiansPerDegree) * 1000000) /
            1000000
        );
      // console.log(res)
    }
    return res.toFixed(2); //返回面积值,单位是平方米
  };

  //封装addLabel，用于完成面积计算后显示结果，绘制到最后一个点上
  const addLabel = (pCartographic, text) => {
    const position = Cesium.Cartesian3.fromRadians(
      pCartographic[pCartographic.length - 1].longitude,
      pCartographic[pCartographic.length - 1].latitude,
      pCartographic[pCartographic.length - 1].height
    );
    const label = viewer.entities.add({
      name: "areaLabel",
      position: position,
      label: {
        text: text + "平方米",
        font: "18px sans-serif",
        fillColor: Cesium.Color.GOLD,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //垂直方向上对齐
        pixelOffset: new Cesium.Cartesian2(20, -20), //偏移量
        heightReference: Cesium.HeightReference.NONE, //高度参考
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
    });
    return label;
  };

  //绘制点
  const drawPoint = (position) => {
    const pointGeometry = viewer.entities.add({
      name: "areaPoint",
      position: position,
      point: {
        pixelSize: 6,
        Color: Cesium.Color.SKYBLUE,
        outlineColor: Cesium.Color.YELLOW,
        outlineWidth: 2,
        disableDepthTestDistance: 4000, //距离4000以下不被遮挡
      },
    });
    return pointGeometry;
  };

  //绘制多边形
  const drawShape = (positionData) => {
    const shape = viewer.entities.add({
      name: "areaShape",
      polygon: {
        hierarchy: positionData,
        material: new Cesium.ColorMaterialProperty(
          Cesium.Color.BLUE.withAlpha(0.5)
        ),
      },
    });
    return shape;
  };

  //鼠标左键单击事件
  handler.setInputAction((event) => {
    const earthPosition = viewer.scene.pickPosition(event.position); //获取点击位置的地理坐标
    if (Cesium.defined(earthPosition)) {
      pCartographic.push(Cesium.Cartographic.fromCartesian(earthPosition)); //将点击位置的地理坐标添加到pCartographic数组
      p.push(earthPosition); //将点击位置的地理坐标添加到p数组
      //第一次单击时
      if (activeShapePoints.length === 0) {
        floatingPoint = drawPoint(earthPosition); //绘制第一个点
        activeShapePoints.push(earthPosition); //将第一个点添加到activeShapePoints数组
        const dynamicPositions = new Cesium.CallbackProperty(() => {
          return new Cesium.PolygonHierarchy(activeShapePoints);
        }, false);
        activeShape = drawShape(dynamicPositions); //绘制第一个多边形
      }
      //添加当前点到activeShapePoints数组,实时渲染动态图
      activeShapePoints.push(earthPosition);
      drawPoint(earthPosition);
    } else {
      alert("请点击地球上的位置");
      return;
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  //鼠标移动事件
  handler.setInputAction((event) => {
    if (Cesium.defined(floatingPoint)) {
      const newPosition = viewer.scene.pickPosition(event.endPosition); //获取鼠标移动结束位置的地理坐标
      if (Cesium.defined(newPosition)) {
        activeShapePoints.pop(); //删除最后一个点
        activeShapePoints.push(newPosition); //添加新的点
      }
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

  //鼠标右键单击事件
  handler.setInputAction(() => {
    activeShapePoints.pop(); //删除最后一个点
    if (activeShapePoints.length) {
      drawShape(activeShapePoints);
    }
    const text = getArea(p);
    addLabel(pCartographic, text); //计算面积并显示结果
    viewer.entities.remove(activeShape); //删除多边形
    viewer.entities.remove(floatingPoint); //删除第一个点
    floatingPoint = undefined; //清空变量
    activeShape = undefined; //清空变量
    activeShapePoints = []; //清空数组
    p = []; //清空数组
    pCartographic = []; //清空数组
    viewer.scene.canvas.style.cursor = "default";
    // handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    handler.destroy(); //销毁事件处理器
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};
